# -*- coding: iso-8859-1 -*-
"""
    Crunchy theme for MoinMoin (with the look of python.org)
    @copyright: 2008 Florian Birée
    
    Based on the MoinMoin - modern theme
    @copyright: 2003-2005 Nir Soffer, Thomas Waldmann
    @license: GNU GPL, see LICENSE for details.
"""

from MoinMoin import wikiutil
from MoinMoin.theme import ThemeBase

class Theme(ThemeBase):
    
    name = "crunchy"
    
    def __init__(self, request):
        """
        Initialize the theme object.

        @param request: the request object
        """
        ThemeBase.__init__(self, request)
        if not hasattr(self.cfg, 'be_wiki_python') or \
                            not self.cfg.be_wiki_python:
            self._be_wiki_python = False
        else:
            self._be_wiki_python = True
            # Replace some functions
            self.header = self.headerWikiPython
            self.footer = self.footerWikiPython
            self.editbarItems = self.editbarItemsWikiPython
            self.pageinfo = self.pageinfoWikiPython
            self.logo = self.logoWikiPython
            
    
    # Page layout
    def header(self, d, **kw):
        """ Assemble wiki header
        
        @param d: parameter dictionary
        @rtype: unicode
        @return: page header html
        """
        html = [
            # Header
            u'<div id="header">',
            self.logo(),
            self.title(d),
            self.searchform(d),
            u'</div>',
            
            # Messages
            self.msg(d),
            
            # Start of page
            self.startPage(),
        ]
        return u'\n'.join(html)
    
    def editorheader(self, d, **kw):
        """ Assemble wiki header for editor
        
        @param d: parameter dictionary
        @rtype: unicode
        @return: page header html
        """
        html = [
            # Header
            u'<div id="header">',
            self.logo(),
            self.title(d),
            u'</div>',
            
            # Messages
            self.msg(d),
            
            # Start of page
            self.startPage(),
        ]
        return u'\n'.join(html)
        
    def footer(self, d, **keywords):
        """ Assemble wiki footer
        
        @param d: parameter dictionary
        @keyword ...:...
        @rtype: unicode
        @return: page footer html
        """
        page = d['page']
        html = [
            # End of page
            self.pageinfo(page),
            self.endPage(),
            
            # Left bar
            u'<div id="menu">',
            self.login_link(d),
            self.navibar(d),
            self.editbar(d),
            u'</div>',
            
            # Footer
            u'<div id="footer">',
            self.credits(d),
            self.showversion(d, **keywords),
            u'</div>',
            ]
        return u'\n'.join(html)
    
    # External links stuff
    def login_link(self, d):
        """ Assemble the username / userprefs link
        
        @param d: parameter dictionary
        @rtype: unicode
        @return: username html
        
        This make the login link as an "external_link" with VLAM
        """
        request = self.request
        _ = request.getText
        userlinks = []
        if not request.user.valid:
            query = {'action': 'login'}
            # special direct-login link if the auth methods want no input
            if request.cfg.auth_login_inputs == ['special_no_input']:
                query['login'] = '1'
            if request.cfg.auth_have_login:
                userlinks.append(d['page'].link_to(request, text=_("Login"),
                                                   querystr=query, id='login',
                                                   rel='nofollow',
                                                   title='external_link',))
            userlinks = [u'<li>%s</li>' % link for link in userlinks]
            html = u'<ul id="username">%s</ul>' % ''.join(userlinks)
            return html
        else:
            return self.username(d)
    
    def editorLink(self, page, use_gui=True):
        """ Return a link to the editor
        
        If the user can't edit, return a disabled edit link.
        
        If use_gui = True and if the user want to show both editors, it will
        display "Edit (Text)", otherwise as "Edit".
        
        This add VLAM markup to force crunchy to open the link as an
        external link
        """
        if 'edit' in self.request.cfg.actions_excluded:
            return ""
        
        if not (page.isWritable() and
                self.request.user.may.write(page.page_name)):
            return self.disabledEdit()
        
        _ = self.request.getText
        querystr = {'action': 'edit'}
        
        guiworks = self.guiworks(page)
        if use_gui and self.showBothEditLinks() and guiworks:
            text = _('Edit (Text)')
            querystr['editor'] = 'text'
            attrs = {'name': 'texteditlink', 'rel': 'nofollow',
                     'title': 'external_link',}
        else:
            text = _('Edit')
            if guiworks:
                # 'textonly' will be upgraded dynamically to 'guipossible' by JS
                querystr['editor'] = 'textonly'
                attrs = {'name': 'editlink', 'rel': 'nofollow',
                         'title': 'external_link',}
            else:
                querystr['editor'] = 'text'
                attrs = {'name': 'texteditlink', 'rel': 'nofollow',
                         'title': 'external_link',}
        
        return page.link_to(self.request, text=text, querystr=querystr, **attrs)
    
    def infoLink(self, page):
        """ Return link to page information
        
        With "external_link" VLAM
        """
        if 'info' in self.request.cfg.actions_excluded:
            return ""
        
        _ = self.request.getText
        return page.link_to(self.request,
                            text=_('Info'),
                            querystr={'action': 'info'}, css_class='nbinfo', rel='nofollow', title='external_link')
    
    def attachmentsLink(self, page):
        """ Return link to page attachments
        
        With "external_link" VLAM
        """
        if 'AttachFile' in self.request.cfg.actions_excluded:
            return ""
        
        _ = self.request.getText
        return page.link_to(self.request,
                            text=_('Attachments'),
                            querystr={'action': 'AttachFile'}, css_class='nbattachments', rel='nofollow', title='external_link')
    
    # be_wiki_python stuff
    def pageinfoWikiPython(self, page):
        """ Return html fragment with page meta data

        Since page information uses translated text, it uses the ui
        language and direction. It looks strange sometimes, but
        translated text using page direction looks worse.
        
        This is a modified version of the default pageinfo function, to add
        an edit link.
        
        @param page: current page
        @rtype: unicode
        @return: page last edit information
        """
        _ = self.request.getText
        html = ''
        if self.shouldShowPageinfo(page):
            info = page.lastEditInfo()
            if info:
                if info['editor']:
                    info = _("last edited %(time)s") % info
                else:
                    info = _("last modified %(time)s") % info
                edit_link = self.editorLink(page, use_gui=False)
                info = "%s  (%s)" % (edit_link, info)
                html = '<p id="pageinfo" class="pythoninfo"%(lang)s>%(info)s</p>\n' % {
                    'lang': self.ui_lang_attr(),
                    'info': info
                    }
        return html
    
    def iconbarWikiPython(self, d):
        """
        Assemble the iconbar - for the be_wiki_python version

        @param d: parameter dictionary
        @rtype: string
        @return: iconbar html
        
        This function is from the 'classic' theme
        """
        iconbar = []
        if self.cfg.page_iconbar and self.request.user.show_toolbar and d['page_name']:
            iconbar.append('<ul id="iconbar">\n')
            icons = self.cfg.page_iconbar[:]
            for icon in icons:
                if icon == "up":
                    if d['page_parent_page']:
                        iconbar.append('<li>%s</li>\n' % self.make_iconlink(icon, d))
                elif icon == "subscribe" and (self.cfg.mail_enabled or self.cfg.jabber_enabled):
                    iconbar.append('<li>%s</li>\n' % self.make_iconlink(
                        ["subscribe", "unsubscribe"][self.request.user.isSubscribedTo([d['page_name']])], d))
                else:
                    iconbar.append('<li>%s</li>\n' % self.make_iconlink(icon, d))
            iconbar.append('</ul>\n')
        return ''.join(iconbar)
    
    def headerWikiPython(self, d, **kw):
        """ Assemble wiki header - for the be_wiki_python version
        
        @param d: parameter dictionary
        @rtype: unicode
        @return: page header html
        """
        html = [
            # Header
            u'<div id="header">',
            self.logo(),
            self.title(d),
            self.searchform(d),
            
            self.iconbarWikiPython(d),
            
            u'</div>',
            
            # Messages
            self.msg(d),
            
            # Start of page
            self.startPage(),
        ]
        return u'\n'.join(html)
    
    def footerWikiPython(self, d, **keywords):
        """ Assemble wiki footer - for the be_wiki_python version
        
        @param d: parameter dictionary
        @keyword ...:...
        @rtype: unicode
        @return: page footer html
        """
        page = d['page']
        # End of page
        html = [
            self.pageinfo(page),
            self.endPage(),
            
            # Left bar
            u'<div id="menu">',
            self.login_link(d),
            u'<ul>',
            u'<li><h4>Navigation</h4>',
                self.navibar(d),
            u'</li>',
            u'<li><h4>Actions</h4>',
                self.editbar(d),
            u'</li>',
            u'</ul>',
            u'</div>',
        ]
        return u'\n'.join(html)
    
    def editbarItemsWikiPython(self, page):
        """ Return list of items to show on the editbar

        This is separate method to make it easy to customize the
        edtibar in sub classes.
        """
        _ = self.request.getText
        editbar_actions = []
        # Attach
        editbar_actions.append(self.attachmentsLink(page))
        
        # Actions built with _genericEditbarItem
        #   (action, name)
        generic_actions = (
            ('Despam', _('Remove Spam')),
            ('LikePages', _('Like Pages')),
            ('LocalSiteMap', _('Local Site Map')),
            ('MyPages', _('My Pages')),
            ('RenderAsDocbook', _('Render as Docbook')),
            ('SpellCheck', _('Check Spelling')),
        )
        for (action, name) in generic_actions:
            editbar_actions.append(self._genericEditbarItem(page, action, name))
        # Subscribe
        editbar_actions.append(self.subscribeLink(page))
        return editbar_actions
    
    def _genericEditbarItem(self, page, action, name):
        """ Return a link to the action page """
        if action in self.request.cfg.actions_excluded:
            return ""
        return page.link_to(self.request,
                            text=name,
                            querystr={'action': action},
                            rel='nofollow',
                            title="external_link",)
    
    def logoWikiPython(self):
        """ Assemble logo with link to front page

        The logo contain an image and or text or any html markup the
        admin inserted in the config file. Everything it enclosed inside
        a div with id="logo".

        @rtype: unicode
        @return: logo html
        """
        html = u''
        if self.cfg.logo_string:
            page = wikiutil.getFrontPage(self.request)
            if hasattr(self.cfg, 'logo_link'):
                logo = u'<a href="%s">%s</a>' % (
                    self.cfg.logo_link,
                    self.cfg.logo_string,
                )
            else:
                logo = page.link_to_raw(self.request, self.cfg.logo_string)
            html = u'''<div id="logo">%s</div>''' % logo
        return html

def execute(request):
    """
    Generate and return a theme object

    @param request: the request object
    @rtype: MoinTheme
    @return: Theme object
    """
    return Theme(request)

